#include <REGX52.H> // 包含51单片机寄存器的头文件

// 数码管显示0-9和一些特殊符号的编码，低电平有效
unsigned char dula[] = {
    0xc0, // 0
    0xf9, // 1
    0xa4, // 2
    0xb0, // 3
    0x99, // 4
    0x92, // 5
    0x82, // 6
    0xf8, // 7
    0x80, // 8
    0x90, // 9
    0xff, // 空白
    0xbf, // 小数点
    0xc6  // 小数点
};

// 数码管位选信号，用于选择显示的数码管位置
unsigned char wela[] = {
    0x01, // 第1位
    0x02, // 第2位
    0x04, // 第3位
    0x08, // 第4位
    0x10, // 第5位
    0x20, // 第6位
    0x40, // 第7位
    0x80  // 第8位
};

// 数码管显示函数，参数Location为位置，Dat为要显示的数字，Point为是否显示小数点
void SEG_Disp(unsigned char Location, unsigned char Dat, bit Point)
{
    P0 = 0xff; // 关闭所有数码管的显示
    P2 = (P2 & 0x1f) | 0xe0; // 设置P2端口的高3位为1，准备输出位选信号
    P2 &= 0x1f; // 输出位选信号，选择数码管位置

    P0 = wela[Location]; // 输出位选信号到P0端口，选择要显示的数码管位置
    P2 = (P2 & 0x1f) | 0xc0; // 设置P2端口的高3位为1，准备输出段选信号
    P2 &= 0x1f; // 输出段选信号，选择数码管的位

    P0 = dula[Dat]; // 输出段选信号到P0端口，显示数字
    if (Point) // 如果需要显示小数点
        P0 &= 0x7f; // 将P0端口的最低位清零，显示小数点
    P2 = (P2 & 0x1f) | 0xe0; // 设置P2端口的高3位为1，准备结束本次显示
    P2 &= 0x1f; // 结束本次显示，恢复P2端口的状态
}